package middleware

import (
	"config-client-v1/init/global"
	j_redis "config-client-v1/init/j-redis"
	"config-client-v1/model"
	"config-client-v1/utils/tools"
	"context"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
	"strings"
	"time"
)

func LoggerToFile() gin.HandlerFunc {

	return func(c *gin.Context) {
		// 开始时间
		startTime := time.Now()
		// 处理请求
		c.Next()
		// 结束时间
		// 执行时间
		latencyTime := time.Since(startTime).String()
		// 请求方式
		reqMethod := c.Request.Method
		// 请求路由
		reqUri := c.Request.RequestURI
		// 状态码
		statusCode := c.Writer.Status()
		// 请求IP
		clientIP := c.ClientIP()

		// 日志格式
		global.MyLogger.WithFields(logrus.Fields{
			"status_code":  statusCode,
			"latency_time": latencyTime,
			"client_ip":    clientIP,
			"req_method":   reqMethod,
			"req_uri":      reqUri,
		}).Info()
	}
}

func CustomRecovery() gin.HandlerFunc {
	return gin.CustomRecovery(func(ctx *gin.Context, any interface{}) {
		defer func() {
			if err := recover(); err != nil {
				fmt.Println("log failed: ", err)
			}
		}()
		global.MyLogger.WithFields(logrus.Fields{
			"status_code": 500,
			"panic_info":  fmt.Sprintf("%s", any),
			"req_uri":     ctx.Request.RequestURI,
		}).Error()
		ctx.String(500, "%s %v", ctx.Request.RequestURI, any)
	})
}

func getCmd(path string) string {
	pathArr := strings.Split(path, "/")
	cmdArr := make([]string, 0)
	for i := 2; i < len(pathArr); i++ {
		cmdArr = append(cmdArr, pathArr[i])
	}
	return strings.Join(cmdArr, "/")
}

func CheckAdminLogin(ctx *gin.Context) {

	pathInfo := strings.Split(ctx.Request.URL.String(), "?")
	path := pathInfo[0]
	cmd := getCmd(path)
	//fmt.Println("当前路由: ", path, " CMD: ", cmd)
	allowList := make(map[string]int) // 不需要登录的接口
	allowList["test"] = 1
	allowList["info"] = 1
	allowList["reset_cache"] = 1
	allowList["std_log_info"] = 1
	allowList["refresh_auth_cache"] = 1
	allowList["captcha"] = 1
	allowList["upload"] = 1
	allowList["do_login"] = 1
	allowList["check_token"] = 1
	allowList["project/list"] = 1
	allowList["project/save"] = 1
	allowList["project/start"] = 1
	allowList["project/stop"] = 1
	allowList["project/detail"] = 1
	allowList["project/delete"] = 1
	allowList["project/export"] = 1
	allowList["project/export_app"] = 1
	allowList["project/import"] = 1
	allowList["project/time_sync"] = 1
	allowList["fs/data_scale"] = 1

	allowList["fs/model_desc"] = 1
	allowList["ws_client_info"] = 1
	allowList["variables_info"] = 1
	allowList["alert_data_map_info"] = 1
	allowList["running_equip_info"] = 1
	allowList["temp_fse"] = 1
	allowList["running_fse"] = 1
	allowList["exp_alarm_items_info"] = 1
	allowList["project/import_check"] = 1
	allowList["project/import_do"] = 1

	authList := make(map[string]int) // 不需要授权的接口
	authList["getMenuList"] = 1
	authList["refreshToken"] = 1
	authList["uploadFile"] = 1
	authList["logout"] = 1

	// 需要验证 session | token
	if allowList[cmd] == 0 {
		token := ctx.GetHeader("Authorization")
		if token == "" {
			ctx.JSON(200, gin.H{
				"code":    3,
				"message": "请登录",
			})
			ctx.Abort()
			return
		}
		tokenInfo, _ := j_redis.RedisDb.Get(context.Background(), token).Result()
		if tokenInfo == "" {
			ctx.JSON(200, gin.H{
				"code":    4,
				"message": "token无效",
			})
			ctx.Abort()
			return
		}
		tokenData := model.UserToken{}
		err := json.Unmarshal([]byte(tokenInfo), &tokenData)
		if err != nil {
			ctx.JSON(200, gin.H{
				"code":    1,
				"message": "json.Unmarshal token Failed",
			})
			return
		}
		if tokenData.Uid == 0 {
			ctx.JSON(200, gin.H{
				"code":    4,
				"message": "token无效",
			})
			ctx.Abort()
			return
		}
		if time.Now().Unix()-tools.StrToTimeStamp(*tokenData.CreateTime) > 3600*24*7 {
			ctx.JSON(200, gin.H{
				"code":    4,
				"message": "token已过期",
				"data": map[string]interface{}{
					"token":                token,
					"tokenData":            tokenData,
					"now":                  time.Now().Unix(),
					"tokenData.CreateTime": tools.StrToTimeStamp(*tokenData.CreateTime),
				},
			})
			ctx.Abort()
			return
		}

		ctx.Set("userToken", tokenData)
	}

}

func CheckApiLogin(ctx *gin.Context) {

	pathInfo := strings.Split(ctx.Request.URL.String(), "?")
	path := pathInfo[0]
	cmd := getCmd(path)
	//fmt.Println("当前路由: ", path, " CMD: ", cmd)
	allowList := make(map[string]int) // 不需要登录的接口
	allowList["frame_save_content"] = 1
	allowList["modbus_db_save_content"] = 1
	allowList["frame_send_condition"] = 1
	allowList["ppe_save_config"] = 1
	allowList["model_save_content"] = 1
	allowList["cmd0603_modify_content"] = 1

	allowList["test"] = 1
	allowList["captcha"] = 1
	allowList["do_login"] = 1
	allowList["check_token"] = 1
	allowList["refresh_auth_cache"] = 1

	allowList["excel/test"] = 1

	authList := make(map[string]int) // 不需要授权的接口
	authList["refreshToken"] = 1
	authList["uploadFile"] = 1
	authList["logout"] = 1

	// 需要验证 session | token
	if allowList[cmd] == 0 {
		token := ctx.GetHeader("Authorization")
		if token == "" {
			ctx.JSON(200, gin.H{
				"code":    3,
				"message": "请登录",
			})
			ctx.Abort()
			return
		}
		tokenInfo, _ := j_redis.RedisDb.Get(context.Background(), token).Result()
		if tokenInfo == "" {
			ctx.JSON(200, gin.H{
				"code":    4,
				"message": "token无效",
			})
			ctx.Abort()
			return
		}
		tokenData := model.UserToken{}
		err := json.Unmarshal([]byte(tokenInfo), &tokenData)
		if err != nil {
			ctx.JSON(200, gin.H{
				"code":    1,
				"message": "json.Unmarshal token Failed",
			})
			return
		}
		if tokenData.Uid == 0 {
			ctx.JSON(200, gin.H{
				"code":    4,
				"message": "token无效",
			})
			ctx.Abort()
			return
		}
		if time.Now().Unix()-tools.StrToTimeStamp(*tokenData.CreateTime) > 3600*24*2 {
			ctx.JSON(200, gin.H{
				"code":    4,
				"message": "token已过期",
			})
			ctx.Abort()
			return
		}
		ctx.Set("userToken", tokenData)
	}

}
